// Builder Pattern - Pages 14-15
package org.effectivejava.examples.chapter02.item02.builder;

/**
 * 问题：当构造方法的参数比较多时，创建对象使用建造者模式（Builder模式）
 * 思路：
 * 1、定义一个静态内部类Builder
 * 2、静态内部类中定义构造方法（设置必须参数）
 * 3、静态内部类中定义其他参数的方法，返回Builder对象
 * 4、静态内部类中定义build()方法返回需要的对象
 * 优点：
 * 1、易于阅读
 * 2、NutritionFacts是不可变的
 */
public class NutritionFacts {
	private final int servingSize;
	private final int servings;
	private final int calories;
	private final int fat;
	private final int sodium;
	private final int carbohydrate;

	// 静态内部类
	public static class Builder {
		// Required parameters
		private final int servingSize;
		private final int servings;

		// Optional parameters - initialized to default values
		private int calories = 0;
		private int fat = 0;
		private int carbohydrate = 0;
		private int sodium = 0;

		// builder构造器
		public Builder(int servingSize, int servings) {
			this.servingSize = servingSize;
			this.servings = servings;
		}

		public Builder calories(int val) {
			calories = val;
			return this;
		}

		public Builder fat(int val) {
			fat = val;
			return this;
		}

		public Builder carbohydrate(int val) {
			carbohydrate = val;
			return this;
		}

		public Builder sodium(int val) {
			sodium = val;
			return this;
		}

		// 定义一个build方法返回自己
		public NutritionFacts build() {
			return new NutritionFacts(this);
		}
	}

	private NutritionFacts(Builder builder) {
		servingSize = builder.servingSize;
		servings = builder.servings;
		calories = builder.calories;
		fat = builder.fat;
		sodium = builder.sodium;
		carbohydrate = builder.carbohydrate;
	}

	public static void main(String[] args) {
		NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
				.calories(100).sodium(35).carbohydrate(27).build();
	}
}